一:区别
1:迁移学习是将已经学习到的知识应用到其他领域,比如通用的语音模型迁移到某个人的语音模型上。
迁移学习就是将一个问题上训练好的模型通过简单的调整使其适用于一个新的问题。
例如利用ImageNet数据集上训练好的Inception-V3模型来解决一个新的图像分类问题,可以保留训练好的Inception-v3模型中所有卷积层的参数,只是替换最后一层全连接层,在最后这一层全连接层之前的网络层称为瓶颈层。而将新的图像通过训练好的卷积神经网络直到瓶颈层的过程可以看成是对图像进行特征提取的过程,瓶颈层输出再通过一个单层的全连接层神经网络可以很好的区分类别,所以有理由相信将瓶颈层的输出的节点向量可以被称为任何图像的更加精简且表达能力更强的特征向量。所以可以直接利用这个训练好的神经网络对图像进行特征提取,然后再将提取得到特征向量作为输入来训练一个新的单层全连接网络来处理分类问题。
但是在数据量足够的情况下,迁移学习的效果不如完全重新训练,但是迁移学习所需要的训练时间和训练样本要远远小于训练完整的模型。
比如把已经训练好的模型的某一层的输出拿出来,然后用一个svm、LR等分类,更好的去利用从某一层输出的特征(也叫知识),这也还是迁移学习的思想,如下前三个是transfer learning经常用到的方法。最后一个是finetune的思想。
把Alexnet里卷积层最后一层输出的特征拿出来,然后直接用SVM分类。这是Transfer Learning,因为你用到了Alexnet中已经学到了的 “知识”。把Vggnet卷积层最后的输出拿出来,用贝叶斯分类器分类。思想基本同上。甚至你可以把Alexnet、Vggnet的输出拿出来进行组合,自己设计一个分类器分类。这个过程中你不仅用了Alexnet的“知识”,也用了Vggnet的“知识”。https://github.com/Gogul09/flower-recognition(此方法实现代码)最后,你也可以直接使用 fine-tune这种方法,在Alexnet的基础上,重新加上全连接层,再去训练网络。
2:finetune(微调):例子:在Alexnet的基础上,我们重新加上一个层再去训练网络,比如再加入一个全连接层,那就是先
固定前面的层,让新加的fc层的loss值降低到一个很低的值,再调低学习率,放开所有层一块去训练这样可以收敛到一个不错的效果。
3:所以我个人认为迁移学习直接将现有的或者从现有的模型中提取出来的有用的东西应用的另一个领域,不在进行训练之前的网络部分,只需要训练我们添加部分网络的部分,将迁移过来的模型的某一层的输出作为我们新增加网络部分的输入。
而finetune就是微调,思想是:利用原有模型的参数信息,作为我们要训练的新的模型的初始化参数,这个新的模型可以和原来一样也可以增添几个层(进行适当的调整)。
4:传统的机器学习框架下,学习的任务是在给定充分训练数据集的基础上学习一个分类模型;然后利用这个学习到的模型来对测试文档进行分类和预测。然而,我们看到机器学习算法在当前web挖掘应用领域存在一个关键问题:一些新出现的领域中的大量训练数据非常难得到。web领域中大量新的数据不断涌现,从传统的新闻,网页,到图片,再到博客,播客等。传统的机器学习需要对每个领域都标定大量训练数据,这将会耗费大量的人力物力,而没有大量的标注数据,会使得很多与学习相关研究与应用无法开展,其次传统的机器学习假设训练数据与测试数据服从相同的数据分布。然而在很多情况下,这种相同分布不满足,通常可能发生的情况如训练数据过期。如果我们有大量的,在不同分布下的训练数据,完全丢弃这些数据也是非常浪费的,如何利用这些数据就是迁移学习主要解决的问题。
迁移学习可以从现有的数据中迁移知识,用来帮助将来的学习。
迁移学习的目标是将从一个环境中学到的知识用来帮助新环境中的学习任务,因此迁移学习不会想传统机器学习那样作同分布假设。
例子:一个会下象棋的人可以更容易的学会下围棋。
迁移学习目前分为一下三个部分:同构空间下基于实例的迁移学习;同构空间下基于特征的迁移学习;异构空间下的迁移学习。
基于实例的迁移学习有更强的知识迁移能力,基于特征的迁移学习具有更广规范的知识迁移能力;异构空间的迁移具有广泛的学习与扩展能力。
迁移学习即一种学习对另一种学习的影响,它广泛的存在于知识技能态度和行为的规范的学习中,任何一种学习都将受先验知识的影响,只要有学习就有迁移,迁移是学习的继续和巩固,优势提高和深化学习的条件,学习与迁移不可分割。
二:迁移学习实例
为了能够快速地训练好自己的花朵图片分类器,我们可以使用别人已经训练好的模型参数,在此基础之上训练我们的模型。这个便属于迁移学习。本文提供训练数据集和代码下载。
原理:卷积神经网络模型总体上可以分为两部分,前面的卷积层和后面的全连接层。卷积层的作用是图片特征的提取,全连接层作用是特征的分类。我们的思路便是在inception-v3网络模型上,修改全连接层,保留卷积层。卷积层的参数使用的是别人已经训练好的,全连接层的参数需要我们初始化并使用我们自己的数据来训练和学习。
和微调fine-tune的区别及迁移学习代码实现/2018-07-15-19-26-42.png)
上面inception-v3模型图红色箭头前面部分是卷积层,后面是全连接层。我们需要修改修改全连接层,同时把模型的最终输出改为5。
由于这里使用了tensorflow框架,所以,我们需要获取上图红色箭头所在位置的张量BOTTLENECK_TENSOR_NAME
(最后一个卷积层激活函数的输出值,个数为2048)以及模型最开始的输入数据的张量JPEG_DATA_TENSOR_NAME
。获取这两个张量的作用是,图片训练数据通过JPEG_DATA_TENSOR_NAME
张量输入模型,通过BOTTLENECK_TENSOR_NAME
张量获取通过卷积层之后的图片特征。
BOTTLENECK_TENSOR_SIZE = 2048
BOTTLENECK_TENSOR_NAME = ‘pool_3/_reshape:0’
JPEG_DATA_TENSOR_NAME = ‘DecodeJpeg/contents:0’
通过下面的代码加载模型,同时获取上面所述的两个张量。
和微调fine-tune的区别及迁移学习代码实现/2018-07-15-19-27-04.png)
最后便是定义交叉熵损失函数。模型使用反向传播训练,而训练的参数并不是模型的所有参数,仅仅是全连接层的参数,卷积层的参数是不变的。
定义交叉熵损失函数。
cross_entropy = tf.nn.softmax_cross_entropy_with_logits(logits=logits, labels=ground_truth_input)
cross_entropy_mean = tf.reduce_mean(cross_entropy)
train_step = tf.train.GradientDescentOptimizer(LEARNING_RATE).minimize(cross_entropy_mean)
那么接下来的是如何给我们的模型输入数据了,这里提供了几个操作数据的函数。由于训练数据集比较小,
先把所有的图片通过JPEG_DATA_TENSOR_NAME
张量输入模型,然后获取BOTTLENECK_TENSOR_NAME
张量的值并保存到硬盘中。
在模型训练的时候,从硬盘中读取所保存的BOTTLENECK_TENSOR_NAME
张量的值作为全连接层的输入数据。因为一张图片可能会被使用多次。
和微调fine-tune的区别及迁移学习代码实现/2018-07-15-19-27-25.png)
运行代码在到时候再去看我的pycharm中的trasform这个项目。
这个代码实现部分参考的是https://blog.csdn.net/liangyihuai/article/details/79219457这个博客的内容
完整代码
1 | # coding=utf8 |